package com.yycx.common.utils.file;

import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.http.HttpHeaders;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

public class ZipUtils {

    private static final int BUFFER_SIZE = 2 * 1024;

    /**
     * Title: toZip Description: 通过指定磁盘路径打包文件
     *
     * @param sourceFiles
     * @param fos
     */
    public static void toZip(List<File> sourceFiles, OutputStream fos) {
        ZipOutputStream zos = null;
        FileInputStream fis = null;
        try {
            // 压缩输出流
            zos = new ZipOutputStream(fos);
            if (!sourceFiles.isEmpty()) {
                for (File file : sourceFiles) {
                    byte[] buf = new byte[BUFFER_SIZE];// 缓存大小
                    // 开始编写新的ZIP文件条目，并将流定位到条目数据的开头。
                    zos.putNextEntry(new ZipEntry(file.getName()));
                    fis = new FileInputStream(file);
                    int len;
                    // read 读取缓冲区数据
                    while ((len = fis.read(buf)) != -1) {
                        zos.write(buf, 0, len);
                    }
                    zos.closeEntry();
                }
            }

        } catch (Exception e) {
            throw new RuntimeException("Compressed file error!!!", e);
        } finally {
            try {
                if (fis != null) {
                    fis.close();
                }
                if (zos != null) {
                    zos.close();
                }
                if (fos != null) {
                    fos.flush();
                    fos.close();
                }
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }

    }

    /**
     * 文件url
     */
    public static final String FILE_URL = "FILE_URL";
    /**
     * 文件别名
     */
    public static final String FILE_NAME = "FILE_NAME";

    /**
     * 文件目录
     */
    public static final String FILE_DIRECTORY = "FILE_DIRECTORY";

    /**
     * 目录分隔符号
     */
    public static final String SLASH = "/";

    /**
     * Title: getToZipUrlMap Description: 封装文件数据
     *
     * @param fileUrl       文件url 必填
     * @param fileName      如果为空则使用原文件名
     * @param fileDirectory 自定义文件目录(注意以一定要以‘/’结尾否则结构出错) 列：一级目录    test/ 多级 test/test1/...
     * @return
     * @throws Exception
     */
    public static Map<String, Object> getToZipUrlMap(String fileUrl, String fileName, String fileDirectory) {
        Map<String, Object> map = new HashMap<String, Object>();
        if (fileUrl != null) {
            StringBuffer buffer = new StringBuffer();
            String[] urls = fileUrl.split("/");
            String[] urlss = urls[urls.length - 1].split("\\.");
            map.put(FILE_URL, fileUrl);
            buffer.append((fileName == null ? urlss[urlss.length - 2] : fileName));
            buffer.append("." + urlss[urlss.length - 1]);
            map.put(FILE_NAME, buffer.toString());
            if (fileDirectory != null) {
                map.put(FILE_DIRECTORY, fileDirectory + SLASH);
            }
        }
        return map;
    }

    /**
     * Title: toZipHTTP Description: 通过http下载打包文件
     *
     * @param fileHttps
     * @param os
     */
    public static void toZipHTTP(List<Map<String, Object>> fileHttps, OutputStream os) {
        ZipOutputStream zos = null;
        URL url = null;
        URLConnection con = null;
        InputStream fis = null;
        try {
            if (!fileHttps.isEmpty()) {
                zos = new ZipOutputStream(os);
                for (Map<String, Object> map : fileHttps) {
                    if (map.containsKey(FILE_URL) && map.containsKey(FILE_NAME)) {
                        // 缓存大小
                        byte[] buf = new byte[BUFFER_SIZE];
                        String urls = map.get(FILE_URL).toString();
                        // 有层级结构，就先创建目录
                        if (map.containsKey(FILE_DIRECTORY)) {
                            zos.putNextEntry(new ZipEntry(map.get(FILE_DIRECTORY).toString() + map.get(FILE_NAME).toString()));
                        } else {
                            zos.putNextEntry(new ZipEntry(map.get(FILE_NAME).toString()));
                        }
                        url = new URL(urls);
                        con = url.openConnection();
                        fis = con.getInputStream();
                        int len;
                        while ((len = fis.read(buf)) != -1) {
                            zos.write(buf, 0, len);
                        }
                        zos.closeEntry();
                    }
                }
            }
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                System.out.println("Packaged successfully!");
                fis.close();
                zos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {
        /*
         * List<File> sourceFiles=new ArrayList<File>(); sourceFiles.add(new
         * File("D:\\zrong2.p12")); sourceFiles.add(new File("E:\\jdk api 1.8.CHM"));
         */
        try {
            List<Map<String, Object>> sourceMapList = new ArrayList<Map<String, Object>>();
            Map<String, Object> map = getToZipUrlMap("http://admin.fpcar.cn/base/static/config/startup.png", "今晚打老虎", "download");
            Map<String, Object> map1 = getToZipUrlMap("http://admin.fpcar.cn/base/static/config/startup.png", "一二三四五", "download" + SLASH + "test");
            sourceMapList.add(map);
            sourceMapList.add(map1);
            OutputStream sdf = new FileOutputStream("D:\\20210416.zip"); // toZip(sourceFiles,sdf);
            toZipHTTP(sourceMapList, sdf);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    /**
     * 导出zip
     *
     * @param excelFileName excel文件名
     * @param zipFileName   zip文件名
     * @param workbook      excel的工作簿
     * @param fileList      附件
     * @param response
     */
    private void exportZip(String excelFileName, String zipFileName, Workbook workbook, List<File> fileList, HttpServletResponse response) {
        try {
            ServletOutputStream outputStream = response.getOutputStream();
            response.setHeader("content-type", "application/octet-stream");
            response.setContentType("application/octet-stream");
            response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=" + new String(zipFileName.getBytes("GB2312"), "ISO8859-1"));
            response.setCharacterEncoding("UTF-8");
            // 直接导出到ZipOutputStream即可
            ZipOutputStream zos = new ZipOutputStream(outputStream, Charset.forName("GBK"));
            byte[] buf = new byte[1024];
            for (File file : fileList) {
                FileInputStream inputStream = new FileInputStream(file);
                ZipEntry zipEntry = new ZipEntry(file.getName());
                zos.putNextEntry(zipEntry);
                int len;
                while ((len = inputStream.read(buf)) != -1) {
                    zos.write(buf, 0, len);
                }
                zos.closeEntry();
                inputStream.close();
            }
            zos.putNextEntry(new ZipEntry(excelFileName));
            workbook.write(zos);
            zos.closeEntry();
            if (zos != null) {
                zos.flush();
                zos.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


}
